//
//  QRScannerConfig.swift
//  CMB250716
//
//  Created by Andy Lau on 18/7/25.
//

import Foundation
import AVFoundation

/// QR扫描器配置管理
struct QRScannerConfig {
    
    // MARK: - 相机配置
    struct Camera {
        /// 是否启用连续自动对焦
        static let enableContinuousAutoFocus = true
        
        /// 对焦模式
        static let focusMode: AVCaptureDevice.FocusMode = .continuousAutoFocus
        
        /// 曝光模式
        static let exposureMode: AVCaptureDevice.ExposureMode = .continuousAutoExposure
        
        /// 白平衡模式
        static let whiteBalanceMode: AVCaptureDevice.WhiteBalanceMode = .continuousAutoWhiteBalance
        
        /// 是否启用平滑自动对焦
        static let enableSmoothAutoFocus = true
    }
    
    // MARK: - 扫描配置
    struct Scanning {
        /// 扫描成功后的延迟时间（秒）
        static let successDelay: TimeInterval = 0.1
        
        /// 是否启用震动反馈
        static let enableHapticFeedback = true
        
        /// 是否启用声音反馈
        static let enableSoundFeedback = false
    }
    
    // MARK: - UI配置
    struct UI {
        /// 扫描框尺寸
        static let scanFrameSize: CGFloat = 250
        
        /// 扫描框圆角
        static let scanFrameCornerRadius: CGFloat = 10
        
        /// 扫描框边框宽度
        static let scanFrameBorderWidth: CGFloat = 2
        
        /// 提示文本
        static let instructionText = "将二维码对准扫描框"
        static let instructionTextEn = "Align QR code within the frame"
        
        /// 取消按钮文本
        static let cancelButtonText = "取消"
        static let cancelButtonTextEn = "Cancel"
    }
    
    // MARK: - URL解析配置
    struct URLParsing {
        /// 桌号URL的基础域名
        static let expectedDomain = "azmobileapp.azurewebsites.net"
        
        /// 桌号URL的路径前缀
        static let expectedPathPrefix = "/Mr_bull/tabs/home"
        
        /// 用于提取桌号的URL参数映射
        struct ParameterMapping {
            /// 位置ID参数名
            static let locationIdParam = "locationId"
            
            /// 方法参数名
            static let methodParam = "method"
            
            /// 查询参数名
            static let queryParam = "q"
            
            /// 令牌参数名
            static let tokenParam = "t"
        }
        
        /// 桌号生成规则
        struct TableNumberGeneration {
            /// 是否使用位置ID的前缀作为桌号
            /// 注意：如果所有QR码的locationId都相同，应设为false并使用其他参数
            static let useLocationIdPrefix = true
            
            /// 是否从URL路径中提取桌号
            static let extractFromURLPath = true
            
            /// URL路径中桌号的正则表达式模式
            /// 支持多种格式：
            /// - "table(\\d+)" 匹配 "table11", "table13"
            /// - "/table/(\\d+)" 匹配 "/table/11", "/table/13"
            /// - "t(\\d+)" 匹配 "t11", "t13"
            /// - "(\\d+)" 匹配任何数字
            static let pathTableNumberPattern = "(?:table|t)?(\\d+)"
            
            /// 是否从查询参数中提取桌号
            static let extractFromQueryParam = true
            
            /// 查询参数中可能包含桌号的参数名列表
            /// 注意：移除了't'参数，避免与token参数冲突
            static let tableNumberQueryParams = ["table", "tableNumber", "tableId", "id", "num"]
            
            /// 位置ID前缀长度（取前4位生成更简洁的桌号）
            static let locationIdPrefixLength = 4
            
            /// 桌号前缀
            static let tablePrefix = "Table"
            
            /// 是否将十六进制转换为十进制显示
            static let convertHexToDecimal = true
            
            /// 是否生成2位数桌号（通过模运算限制在10-99范围）
            /// 注意：启用此选项会导致不同locationId映射到相同桌号，建议设为false
            static let generateTwoDigitNumber = true
            
            /// 2位数桌号的最小值（包含）
            static let twoDigitMinValue = 0
            
            /// 2位数桌号的最大值
            static let twoDigitMaxValue = 99
            
            /// 备用桌号（当URL解析失败时使用）
            static let fallbackTableNumber = "未知桌号"
        }
    }
    
    // MARK: - 通知配置
    struct Notifications {
        /// QR码扫描成功通知
        static let qrCodeScannedNotification = "QRCodeScanned"
        
        /// QR码扫描失败通知
        static let qrScanFailedNotification = "QRScanFailed"
    }
    
    // MARK: - Token映射表
    /// 根据token前缀获取对应的桌号
    /// - Parameter tokenPrefix: token的前8个字符
    /// - Returns: 对应的桌号（1-35），如果未找到则返回nil
    private static func getTableNumberFromToken(_ tokenPrefix: String) -> Int? {
        // Cu Mr Bull餐厅的桌号映射表
        // 每个token前缀对应一个特定的桌号
        let tokenToTableMap: [String: Int] = [
            "54bc6c63": 1,  "23ef462e": 2,  "1889c623": 3,  "3a9b4684": 4,  "513ef831": 5,
            "2869086f": 6,  "a10c7689": 7,  "9e3b1401": 8,  "11e611d4": 9,  "c90755ff": 10,
            "ea4a8e08": 11, "d20af3e5": 12, "a857967b": 13, "50fcbcf0": 14, "df9ecabd": 15,
            "32da2f27": 16, "807a3c32": 17, "26cae4b2": 18, "1e2ae53e": 19, "18a3b5f7": 20,
            "5c0e16ef": 21, "f9dfd5e0": 22, "cb3251f4": 23, "04ee6af1": 24, "dc70cf5a": 25,
            "c94f35a9": 26, "2f82eac8": 27, "3c90e9b4": 28, "881aec61": 29, "32774812": 30,
            "205e2e23": 31, "2a545b88": 32, "2514ba3f": 33, "7276d881": 34, "6d8968fc": 35
        ]
        
        return tokenToTableMap[tokenPrefix]
    }
    
    // MARK: - URL解析方法
    /// 从QR码URL中解析桌号
    /// - Parameter qrCodeContent: QR码内容
    /// - Returns: 解析后的桌号
    static func parseTableNumber(from qrCodeContent: String) -> String {
        print("\n🔍 [解析调试] 开始解析: \(qrCodeContent)")
        
        // 尝试解析为URL
        guard let url = URL(string: qrCodeContent) else {
            print("❌ [解析调试] 无效URL格式，尝试从原始内容提取数字")
            // 尝试从原始内容中提取数字
            let numberPattern = "(\\d+)"
            if let regex = try? NSRegularExpression(pattern: numberPattern, options: []),
               let match = regex.firstMatch(in: qrCodeContent, options: [], range: NSRange(location: 0, length: qrCodeContent.count)),
               match.numberOfRanges > 1 {
                let range = match.range(at: 1)
                if let swiftRange = Range(range, in: qrCodeContent) {
                    let extractedNumber = String(qrCodeContent[swiftRange])
                    let result = URLParsing.TableNumberGeneration.tablePrefix + extractedNumber
                    print("✅ [解析调试] 从原始内容提取到桌号: \(result)")
                    return result
                }
            }
            print("❌ [解析调试] 原始内容中未找到数字，返回默认值")
            return URLParsing.TableNumberGeneration.fallbackTableNumber
        }
        
        // 检查URL是否符合预期格式
        let isValidDomain = url.host == URLParsing.expectedDomain
        let isValidPath = url.path.hasPrefix(URLParsing.expectedPathPrefix)
        
        print("🔍 [解析调试] URL分析:")
        print("   - Host: \(url.host ?? "无") (期望: \(URLParsing.expectedDomain)) \(isValidDomain ? "✅" : "❌")")
        print("   - Path: \(url.path) (期望前缀: \(URLParsing.expectedPathPrefix)) \(isValidPath ? "✅" : "❌")")
        print("   - Query: \(url.query ?? "无")")
        
        // 如果URL格式不符合预期，但仍然是URL，尝试从中提取信息
         if !isValidDomain || !isValidPath {
             print("⚠️ [解析调试] URL格式不符合预期，但仍尝试解析")
         }
         
         // 解析URL参数
         guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else {
             print("❌ [解析调试] 无法解析URL组件，尝试从原始内容提取数字")
             // 尝试从原始内容中提取数字
             let numberPattern = "(\\d+)"
             if let regex = try? NSRegularExpression(pattern: numberPattern, options: []),
                let match = regex.firstMatch(in: qrCodeContent, options: [], range: NSRange(location: 0, length: qrCodeContent.count)),
                match.numberOfRanges > 1 {
                 let range = match.range(at: 1)
                 if let swiftRange = Range(range, in: qrCodeContent) {
                     let extractedNumber = String(qrCodeContent[swiftRange])
                     let result = URLParsing.TableNumberGeneration.tablePrefix + extractedNumber
                     print("✅ [解析调试] 从原始内容提取到桌号: \(result)")
                     return result
                 }
             }
             print("❌ [解析调试] 原始内容中未找到数字，返回默认值")
             return URLParsing.TableNumberGeneration.fallbackTableNumber
         }
         
         let queryItems = components.queryItems ?? []
        
        // 创建参数字典
        let parameters: [String: String] = Dictionary(uniqueKeysWithValues: queryItems.compactMap { item in
            guard let value = item.value else { return nil }
            return (item.name, value)
        })
        
        // 优先级1：使用token参数('t')生成桌号 - 最高优先级
        if let token = parameters[URLParsing.ParameterMapping.tokenParam] {
            print("🔍 [解析调试] 尝试从token生成桌号: \(token)")
            
            // 使用token前缀映射表
            let tokenPrefix = String(token.prefix(8)) // 取前8个字符作为唯一标识
            if let tableNumber = getTableNumberFromToken(tokenPrefix) {
                let formattedNumber = String(format: "%02d", tableNumber)
                let result = URLParsing.TableNumberGeneration.tablePrefix + formattedNumber
                print("✅ [解析调试] 从token映射到桌号: \(result)")
                return result
            }
            print("❌ [解析调试] token未在映射表中找到")
        }
        
        // 优先级2：使用位置ID的前缀作为桌号（备用方案）
        if URLParsing.TableNumberGeneration.useLocationIdPrefix,
           let locationId = parameters[URLParsing.ParameterMapping.locationIdParam] {
            print("🔍 [解析调试] 尝试从locationId生成桌号: \(locationId)")
            let prefix = String(locationId.prefix(URLParsing.TableNumberGeneration.locationIdPrefixLength))
            
            // 如果配置为转换十六进制为十进制
            if URLParsing.TableNumberGeneration.convertHexToDecimal,
               let hexValue = Int(prefix, radix: 16) {
                
                // 如果配置为生成2位数桌号
                if URLParsing.TableNumberGeneration.generateTwoDigitNumber {
                    let minValue = URLParsing.TableNumberGeneration.twoDigitMinValue
                    let maxValue = URLParsing.TableNumberGeneration.twoDigitMaxValue
                    let range = maxValue - minValue + 1
                    // 使用简化的映射算法：取前缀的最后一个字符的十六进制值
                    // 这样可以提供更均匀的分布，同时保持确定性
                    let lastChar = prefix.last ?? "0"
                    let mappingValue = lastChar.hexDigitValue ?? 0
                    let twoDigitNumber = (mappingValue % range) + minValue
                    let formattedNumber = String(format: "%02d", twoDigitNumber)
                    let result = URLParsing.TableNumberGeneration.tablePrefix + formattedNumber
                    print("✅ [解析调试] 从locationId生成桌号: \(result)")
                    return result
                } else {
                    let result = URLParsing.TableNumberGeneration.tablePrefix + String(hexValue)
                    print("✅ [解析调试] 从locationId生成桌号: \(result)")
                    return result
                }
            } else {
                let result = URLParsing.TableNumberGeneration.tablePrefix + prefix
                print("✅ [解析调试] 从locationId生成桌号: \(result)")
                return result
            }
        }
        
        // 优先级3：从查询参数中提取桌号（尝试多个参数名）
        if URLParsing.TableNumberGeneration.extractFromQueryParam {
            print("🔍 [解析调试] 尝试从查询参数提取桌号")
            print("   - 可用参数: \(parameters.keys.joined(separator: ", "))")
            
            for paramName in URLParsing.TableNumberGeneration.tableNumberQueryParams {
                if let tableNumber = parameters[paramName] {
                    let result = URLParsing.TableNumberGeneration.tablePrefix + tableNumber
                    print("✅ [解析调试] 从查询参数'\(paramName)'提取到桌号: \(result)")
                    return result
                }
            }
            print("❌ [解析调试] 未在查询参数中找到桌号")
        }
        
        // 优先级4：从URL路径中提取桌号
        if URLParsing.TableNumberGeneration.extractFromURLPath {
            print("🔍 [解析调试] 尝试从URL路径提取桌号")
            print("   - 正则模式: \(URLParsing.TableNumberGeneration.pathTableNumberPattern)")
            print("   - 完整URL: \(url.absoluteString)")
            
            let pattern = URLParsing.TableNumberGeneration.pathTableNumberPattern
            if let regex = try? NSRegularExpression(pattern: pattern, options: []),
               let match = regex.firstMatch(in: url.absoluteString, options: [], range: NSRange(location: 0, length: url.absoluteString.count)),
               match.numberOfRanges > 1 {
                let range = match.range(at: 1)
                if let swiftRange = Range(range, in: url.absoluteString) {
                    let tableNumber = String(url.absoluteString[swiftRange])
                    let result = URLParsing.TableNumberGeneration.tablePrefix + tableNumber
                    print("✅ [解析调试] 从URL路径提取到桌号: \(result)")
                    return result
                }
            }
            print("❌ [解析调试] 未在URL路径中找到桌号")
        }
        
        // 优先级5：使用method参数
        if let method = parameters[URLParsing.ParameterMapping.methodParam] {
            let result = URLParsing.TableNumberGeneration.tablePrefix + method
            print("✅ [解析调试] 从method参数提取到桌号: \(result)")
            return result
        }
        
        // 最终备用方案：如果URL格式不符合预期，尝试从原始内容中提取数字
        if !isValidDomain || !isValidPath {
            print("🔍 [解析调试] 尝试从原始内容提取数字")
            let numberPattern = "(\\d+)"
            if let regex = try? NSRegularExpression(pattern: numberPattern, options: []),
               let match = regex.firstMatch(in: qrCodeContent, options: [], range: NSRange(location: 0, length: qrCodeContent.count)),
               match.numberOfRanges > 1 {
                let range = match.range(at: 1)
                if let swiftRange = Range(range, in: qrCodeContent) {
                    let extractedNumber = String(qrCodeContent[swiftRange])
                    let result = URLParsing.TableNumberGeneration.tablePrefix + extractedNumber
                    print("✅ [解析调试] 从原始内容提取到桌号: \(result)")
                    return result
                }
            }
        }
        
        // 最终备用方案
        print("❌ [解析调试] 所有方法都未找到桌号，返回默认值")
        return URLParsing.TableNumberGeneration.fallbackTableNumber
    }
}